package com.bwie.search.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.pinyougou.pojo.TbItem;
import com.pinyougou.sellergoods.service.ItemSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.*;
import org.springframework.data.solr.core.query.result.*;

import java.util.*;

@Service(timeout=3000)
public class ItemSearchServiceImpl implements ItemSearchService {

    @Autowired
    private SolrTemplate solrTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 搜索主入口
     * @param searchCondition
     * @return
     */
    @Override
    public Map<String, Object> search(Map searchCondition) {

        //关键词去空格， 空格可能会影响查询到的结果
        String keywords = (String) searchCondition.get("keywords");

        searchCondition.put("keywords",keywords.replace(" ",""));

        //关键词高亮 + 分类，品牌，规格选项过滤 查询
        Map map = searchByWordsKey(searchCondition);

        //查询关联的分类集合
        List<String> list = searchCategoryList(searchCondition);

        //分类集合
        map.put("categoryList",list);

        if (!"".equals(searchCondition.get("category"))) {  //选中了分类

            //查询品牌和规格,并入现有map
            Map<String, Object> brandAndSpecMap = searchBrandAndSpec((String) searchCondition.get("category"));
            map.putAll(brandAndSpecMap);

        }else {  //没有选中分类，所以获取查询到的第一个分类

            if (list.size() > 0) {
                String category = list.get(0);

                //查询品牌和规格,并入现有map
                Map<String, Object> brandAndSpecMap = searchBrandAndSpec(category);
                map.putAll(brandAndSpecMap);
            }

        }

        return map;

    }


    /**
     * 从缓存中读取品牌和规格
     * @param category
     * @return
     */
    public Map<String, Object> searchBrandAndSpec(String category) {

        Map<String, Object> map = new HashMap<>();

        //根据分类获取模板id
        Long typeId = (Long) redisTemplate.boundHashOps("itemCat").get(category);

        if (typeId != null) {

            //查询分类和规格
            List brandList = (List) redisTemplate.boundHashOps("brandList").get(typeId);
            map.put("brandList",brandList);

            //查询分类和规格
            List specList = (List) redisTemplate.boundHashOps("specList").get(typeId);
            map.put("specList",specList);

        }

        return map;
    }

    /**
     * 关键词高亮查询
     * @param searchMap
     * @return
     */
    public Map<String, Object> searchByWordsKey(Map<String, Object> searchMap) {

        //高亮查询对象
        HighlightQuery query = new SimpleHighlightQuery();

        //实例化高亮选项
        HighlightOptions highlightOptions = new HighlightOptions();

        //高亮选项添加高亮字段
        highlightOptions.addField("item_title");

        //设置前后缀
        highlightOptions.setSimplePrefix("<em style='color:pink'>");
        highlightOptions.setSimplePostfix("</em>");

        //高亮选项设置到查询
        query.setHighlightOptions(highlightOptions);

        //根据域构造条件关键词查询
        Criteria criteria = new Criteria("item_keywords").is((String) searchMap.get("keywords"));

        query.addCriteria(criteria);



        //根据分类过滤查询   TODO:过滤跟条件的区别？   搜索结果匹配度的分值（score）
        if (! "".equals(searchMap.get("category"))) {

            Criteria catCriteria = new Criteria("item_category").is(searchMap.get("category"));

            SimpleFilterQuery simpleFilterQuery = new SimpleFilterQuery(catCriteria);

            query.addFilterQuery(simpleFilterQuery);

        }


        //根据品牌过滤查询
        if (! "".equals(searchMap.get("brand"))) {

            Criteria catCriteria = new Criteria("item_brand").is(searchMap.get("brand"));

            SimpleFilterQuery simpleFilterQuery = new SimpleFilterQuery(catCriteria);

            query.addFilterQuery(simpleFilterQuery);

        }

        //根据规格选项过滤查询
        if (searchMap.get("spec") != null) {

            //获取到选中的规格选项列表
            Map specList = (Map) searchMap.get("spec");

            //转换为集合
            Set<String> set = specList.keySet();

            //获取到每一个规格名
            for (String key : set) {

                //构造查询条件
                Criteria criteria1 = new Criteria("item_spec_" + key).is(specList.get(key));

                //创建条件过滤
                SimpleFilterQuery simpleFilterQuery = new SimpleFilterQuery(criteria);

                query.addFilterQuery(simpleFilterQuery);

            }

        }

        //价格区间查询
        String price = (String) searchMap.get("price");
        if (!"".equals(price)) { //不为空判断

            String[] split = price.split("-");

            if (!"0".equals(split[0])) {  //判断起始价不等于0

                Criteria criteriaLeft = new Criteria("item_price").greaterThanEqual(split[0]);

                SimpleFilterQuery simpleFilterQuery = new SimpleFilterQuery(criteriaLeft);

                query.addFilterQuery(simpleFilterQuery);

            }

            if (!"*".equals(split[1])) {  //判断结束价价不等于*

                Criteria criteriaLeft = new Criteria("item_price").lessThanEqual(split[1]);

                SimpleFilterQuery simpleFilterQuery = new SimpleFilterQuery(criteriaLeft);

                query.addFilterQuery(simpleFilterQuery);

            }

        }


        //分页查询信息
        Integer pageNum = (Integer) searchMap.get("pageNum");

        Integer pageSize = (Integer) searchMap.get("pageSize");

        if (pageNum == null) { //判断是否有页码

            //设置默认值
            pageNum = 1;

        }

        if (pageSize == null) { //判断是否有每页数据

            //设置默认值
            pageSize = 20;

        }

        //起始页码
        query.setOffset(pageNum);
        //每页显示数量
        query.setRows(pageSize);

        //分页后进行排序，比分页前排序效率要高
        String sortField = (String) searchMap.get("sortField");
        String sortType = (String) searchMap.get("sortType");
        if ( sortType != null && !"".equals(sortType) && sortField != null && !"".equals(sortField) ) { //不为空

            if (sortType.equals("ASC")) {
                //排序对象
                Sort sort = new Sort(Sort.Direction.ASC,"item_"+sortField);
                //添加排序信息
                query.addSort(sort);
            }

            if (sortType.equals("DESC")) {
                //排序对象
                Sort sort = new Sort(Sort.Direction.DESC,"item_"+sortField);
                //添加排序信息
                query.addSort(sort);
            }

        }


        //根据高亮分页查询
        HighlightPage<TbItem> highlightPage = solrTemplate.queryForHighlightPage(query, TbItem.class);

        //高亮入口集合
        List<HighlightEntry<TbItem>> highlighted = highlightPage.getHighlighted();

        for (HighlightEntry<TbItem> h : highlighted) {

            //原实体
            TbItem entity = h.getEntity();

            //判断高亮实体的个数和高亮片段的个数
            if (h.getHighlights().size()>0 && h.getHighlights().get(0).getSnipplets().size()>0) {

                //将原实体的指定字段替换为高亮片段
                entity.setTitle(h.getHighlights().get(0).getSnipplets().get(0));

            }

        }

        Map<String, Object> map = new HashMap<>();

        //查询到的数据
        map.put("rows",highlightPage.getContent());

        //分页信息
        map.put("totalPages",highlightPage.getTotalPages());
        map.put("total",highlightPage.getTotalElements());

        return map;

    }

    /**
     * 分类分组查询
     * 根据关键词查询有关联的分类集合，通过分组去重
     * @param searchMap
     * @return
     */
    public List<String> searchCategoryList(Map searchMap) {

        //查询对象
        SimpleQuery query = new SimpleQuery("*:*");

        //关键词查询
        Criteria criteria = new Criteria("item_keywords").is((String) searchMap.get("keywords"));

        query.addCriteria(criteria);


        //创建分组选项
        GroupOptions groupOptions = new GroupOptions();

        //根据指定域分类 == group by xxx
        groupOptions.addGroupByField("item_category");

        //设置分组选项
        query.setGroupOptions(groupOptions);

        //分组查询
        GroupPage<TbItem> groupPage = solrTemplate.queryForGroupPage(query, TbItem.class);

        //相当于select xxx ,查询结果
        GroupResult<TbItem> groupResult = groupPage.getGroupResult("item_category");

        //入口,封装
        Page<GroupEntry<TbItem>> groupEntries = groupResult.getGroupEntries();

        //结果集合
        List<GroupEntry<TbItem>> content = groupEntries.getContent();

        //返回结果
        List<String> list = new ArrayList<>();

        for (GroupEntry<TbItem> tbItemGroupEntry : content) {

            //获取分组值
            String groupValue = tbItemGroupEntry.getGroupValue();

            list.add(groupValue);
        }

        return list;

    }

}
